package utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import models.Model;

import org.apache.log4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @author ArtyomyuS
 * 
 * @param <T>
 */
@Component
@Scope("prototype")
public class Utils<T> {
	private static final Logger LOGGER = Logger.getLogger(Utils.class);

	/**
	 * @param model
	 * @return
	 */
	public T convertModelToEntity(Model model) {
		LOGGER.info("Start method convertModelToEntity();");
		T entity = null;
		T entityPlain = getEntity(model.getClass().getSimpleName());
		try {
			entity = transferModelToEntity(entityPlain, model);
		} catch (IllegalArgumentException e) {
			//
		}
		LOGGER.info("End method convertModelToEntity();");
		return entity;
	}

	@SuppressWarnings("unchecked")
	public T getEntity(String name) {
		LOGGER.info("Start method getEntity();");
		String path = "dao.entity.";
		Class<?> cl = null;
		T entity = null;
		try {
			cl = Class.forName(path + validateEntityName(name));
			entity = (T) cl.newInstance();
			LOGGER.info("Entity created: " + entity);
		} catch (ClassNotFoundException e) {
		} catch (InstantiationException e) {
		} catch (IllegalAccessException e) {
		}
		LOGGER.info("End method getEntity();");
		return entity;
	}

	private String validateEntityName(String name) {
		if (name.indexOf("Model") != -1) {
			name = name.substring(0, name.indexOf("Model"));
		}
		LOGGER.info("Start method validateEntityName(), return name: " + name);
		return name;
	}

	/*
	 * Find getter value on model, end fill it to entity setter
	 */
	private T transferModelToEntity(T entity, Model model) {
		List<Method> getters = getGetters(model);
		for (Method getter : getters) {
			String modelMethodName = getSimpleMethodName(getter, "get");
			for (Method setter : entity.getClass().getDeclaredMethods()) {
				String entityMethodName = getSimpleMethodName(setter, "set");
				try {
					if (modelMethodName.equalsIgnoreCase(entityMethodName)) {
						setter.invoke(entity, getter.invoke(model));
					}
				} catch (IllegalAccessException e) {
				} catch (IllegalArgumentException e) {
				} catch (InvocationTargetException e) {
				}
			}
		}

		// }
		return entity;
	}

	private String getSimpleMethodName(Method method, String type) {
		return method.toString().substring(method.toString().indexOf(type) + 3,
				method.toString().indexOf("("));
	}

	private List<Method> getGetters(Model model) {
		Method[] methods = model.getClass().getDeclaredMethods();
		List<Method> returnMethods = new ArrayList<Method>();
		for (Method method : methods) {
			if (method.toString().indexOf("get") != -1) {
				returnMethods.add(method);
			}
		}
		return returnMethods;
	}
}
